<!--
 * @Descripttion: 图片预览组件
 * @version: V1.0.0.1
 * @Author: zhaozhenzhuo
 * @Date: 2025-11-03 10:07:55
 * @LastEditors: zhaozhenzhuo
 * @LastEditTime: 2025-11-03 10:07:55
-->
<template>
	<div class="preview-file-wrapper">
		<!-- 视角列表 -->
		<div
			class="list-wrap"
			:class="{ reverse: (videoTime || videoTime === 0) && (!picArr || !picArr.length) }"
		>
			<div v-if="picArr && picArr.length" class="stream-list">
				<div
					v-for="(item, index) in picArr"
					:key="index"
					class="stream-item"
					:class="{ active: activeIndex === index }"
					@click="onClickStreamHandle(item, index)"
				>
					{{ item.streamName || '未知视角' }}
				</div>
			</div>
			<div
				v-if="videoTime || videoTime === 0"
				class="stream-item record-btn"
				@click="onLookVideoHandle"
			>
				查看录像
			</div>
		</div>
		<!-- 图片预览 -->
		<div class="img-wrapper">
			<img v-if="showMode === 1" :src="picUrl" />
			<div v-else class="preview-canvas-wrap"></div>
		</div>
	</div>
</template>

<script setup lang="ts">
import { onMounted, ref, nextTick, onUnmounted } from 'vue';
import DrawInPicture from '@/assets/js/drawInPicture';
import type { PreviewInfoType, BehaviorDataItemType } from './PreviewFile.type';

const props = withDefaults(
	defineProps<{
		previewInfo: PreviewInfoType | null;
	}>(),
	{
		previewInfo: null
	}
);

const emit = defineEmits<{
	(e: 'changeVideoTime', time: number): void; // 切换视频时间
	(e: 'closePreview'): void; // 关闭预览
}>();

const timer = ref<ReturnType<typeof setTimeout> | null>(null);

onMounted(() => {
	// 初始化
	init();
	// 监听窗口大小变化
	window.addEventListener('resize', onWindowResizeHandle);
});

onUnmounted(() => {
	window.removeEventListener('resize', onWindowResizeHandle);
	if (timer.value) {
		clearTimeout(timer.value);
	}
});

// 图片列表
const picArr = ref<BehaviorDataItemType[]>([]);
// 图片地址
const picUrl = ref<string>('static/img/ai-default.jpg');
// 当前图片对应的视频时间
const videoTime = ref<number | null>(null);
// 初始化
const init = () => {
	picArr.value = [];
	// 获取图片 type=1传入字符串，只展示一张图片；type=2传入数组，展示多张图片
	if (props.previewInfo && props.previewInfo.transFileUrl) {
		if (props.previewInfo.type === 2 && typeof props.previewInfo.transFileUrl === 'object') {
			// 传入数组
			if (props.previewInfo.transFileUrl && props.previewInfo.transFileUrl.length) {
				picArr.value = props.previewInfo.transFileUrl;
				videoTime.value = picArr.value[0].videoTime ?? null;
				initCanvasImg(props.previewInfo.transFileUrl[0]);
			} else {
				videoTime.value = null;
				picUrl.value = 'static/img/ai-default.jpg';
			}
		} else if (typeof props.previewInfo.transFileUrl === 'string') {
			videoTime.value = props.previewInfo.videoTime ?? null;
			// 传入字符串
			isImgUrlValid(props.previewInfo.transFileUrl)
				.then((result) => {
					if (result && typeof props.previewInfo?.transFileUrl === 'string') {
						// 图片展示
						picUrl.value = props.previewInfo?.transFileUrl;
					} else {
						picUrl.value = 'static/img/ai-default.jpg';
					}
				})
				.catch(() => {
					picUrl.value = 'static/img/ai-default.jpg';
				});
		}
	} else {
		videoTime.value = null;
		picUrl.value = 'static/img/ai-default.jpg';
	}
};

// 判断图片地址是否存在 有效返回true, 无效返回false
const isImgUrlValid = (imgurl: string) => {
	return new Promise((resolve, reject) => {
		const ImgObj = new Image(); // 判断图片是否存在
		ImgObj.src = imgurl;
		ImgObj.onload = (res) => {
			resolve(res);
		};
		ImgObj.onerror = (err) => {
			reject(err);
		};
	}).catch((err) => {
		console.log(err);
	});
};

// 实例对象
const drawInPicture = ref<DrawInPicture | null>(null);
// 展示的类型 1: 图片展示 2: canvas展示
const showMode = ref<1 | 2>(1);
// 渲染canvas图片
const initCanvasImg = async (item: BehaviorDataItemType) => {
	try {
		const result = await isImgUrlValid(item.picUrl);
		if (result) {
			// canvas展示
			showMode.value = 2;
			picUrl.value = item.picUrl;
			nextTick(async () => {
				// 创建实例
				drawInPicture.value = new DrawInPicture(
					document.querySelector('.preview-canvas-wrap') as HTMLElement
				);
				// 创建画布
				await drawInPicture.value.createCanvas(picUrl.value);
				// 设置绘制模式为描边矩形(可以不设置)
				drawInPicture.value.setCanvasMode('stroke');
				// 设置样式(可以不设置)
				drawInPicture.value.setStyle({
					color: '#00a8ff',
					lineWidth: 3
				});
				// 处理坐标格式 "[(1,2,3,4),(5,6,7,8)]"处理成 [{x:1,y:2,width:3,height:4}]
				if (item.coordinate) {
					const _str = item.coordinate.substring(2, item.coordinate.length - 2);
					const _arr = _str.split('),(');
					const _coordinateArr: { x: number; y: number; width: number; height: number }[] = [];
					_arr.forEach((i) => {
						const _numArr = i.split(',');
						_coordinateArr.push({
							x: Number(_numArr[0]),
							y: Number(_numArr[1]),
							width: Number(_numArr[2]),
							height: Number(_numArr[3])
						});
					});
					// 绘制矩形
					drawInPicture.value.drawRect(_coordinateArr);
				}
			});
		} else {
			picUrl.value = 'static/img/ai-default.jpg';
		}
	} catch (err) {
		console.log(err);
		picUrl.value = 'static/img/ai-default.jpg';
	}
};

// 重新渲染canvas图片
const reInitCanvasImg = (item: BehaviorDataItemType) => {
	nextTick(async () => {
		if (drawInPicture.value) {
			// 重新创建画布
			await drawInPicture.value.createCanvas(picUrl.value);
			// 处理坐标格式 "[(1,2,3,4),(5,6,7,8)]"处理成 [{x:1,y:2,width:3,height:4}]
			if (item.coordinate) {
				const _str = item.coordinate.substring(2, item.coordinate.length - 2);
				const _arr = _str.split('),(');
				const _coordinateArr: { x: number; y: number; width: number; height: number }[] = [];
				_arr.forEach((i) => {
					const _numArr = i.split(',');
					_coordinateArr.push({
						x: Number(_numArr[0]),
						y: Number(_numArr[1]),
						width: Number(_numArr[2]),
						height: Number(_numArr[3])
					});
				});
				// 绘制矩形
				drawInPicture.value.drawRect(_coordinateArr);
			}
		}
	});
};

// 当前高亮的信源
const activeIndex = ref<number>(0);
// 点击视角
const onClickStreamHandle = (item: BehaviorDataItemType, index: number) => {
	if (activeIndex.value === index) {
		return;
	}
	activeIndex.value = index;
	showMode.value = 1;
	picUrl.value = 'static/img/ai-default.jpg';
	videoTime.value = item.videoTime ?? null;
	initCanvasImg(item);
};

// 窗口大小变化
const onWindowResizeHandle = () => {
	if (timer.value) {
		clearTimeout(timer.value);
	}
	if (drawInPicture.value) {
		drawInPicture.value.destroyCanvas();
	}
	timer.value = setTimeout(() => {
		reInitCanvasImg(picArr.value[activeIndex.value]);
	}, 300);
};

// 查看录像
const onLookVideoHandle = () => {
	// 通知视频组件弹框
	if (props.previewInfo?.analysisType === 1) {
		// 老师
		emit('changeVideoTime', videoTime.value as number);
	} else {
		// 学生
		emit('changeVideoTime', videoTime.value as number);
	}
	emit('closePreview');
};
</script>

<style lang="scss" scoped>
.preview-file-wrapper {
	.img-wrapper {
		aspect-ratio: 16 / 9;

		img,
		.preview-canvas-wrap {
			width: 100%;
			height: 100%;
		}
	}

	.list-wrap {
		display: flex;
		justify-content: space-between;
	}

	.reverse {
		flex-direction: row-reverse;
	}

	.stream-list {
		display: flex;
		flex-wrap: nowrap;
	}

	.stream-item {
		margin-right: 1.8rem;
		margin-bottom: 1rem;
		padding: 0 1rem;
		height: 3rem;
		background-color: rgba($color: $bg-block-color-dark, $alpha: 0.1);
		border-radius: 0.4rem;
		font-size: $font-size-small-1;
		color: $text-color-secondary;
		line-height: 3rem;
		text-align: center;
		cursor: pointer;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.record-btn {
		margin-right: 0;
	}

	.stream-item.active,
	.stream-item:hover {
		color: $text-color-brand;
		background-color: rgba($color: $color-brand, $alpha: 0.12);
	}
}
</style>
